
/**********************************************************************************\
** 文件名称: beep.c
** 创建人员: YCG
** 创建日期: 2018-12-14
** 文档描述:
** 版本代号: V0.1
** 版本说明: 初始版本
\********************************************************************************/
#include "beep.h"


Beep_t  BEEP[1];

static uint8_t BeepMode = 0;


Staff_t const d1[] = {{22, 20}};
Staff_t const d2[] = {{22, 20}, {0, 125}, {22, 20}};
Staff_t const d3[] = {{22, 20}, {0, 125}, {22, 20}, {0, 125}, {22, 20}};

Staff_t const b1[] = {{40, 40}};
Staff_t const b2[] = {{40, 40},{0, 125},{40, 40}};
Staff_t const b3[] = {{40, 40},{0, 125},{22, 40},{0, 125},{40, 40}};

Staff_t const birthday [] = {
    {5, 125}, {5, 125}, {6, 250}, {5, 250}, {1, 250}, {7, 250}, {0, 250},
    {5, 125}, {5, 125}, {6, 250}, {5, 250}, {2, 250}, {1, 250}, {0, 250},
    {5, 125}, {5, 125}, {5, 250}, {3, 250}, {1, 250}, {7, 250}, {6, 500}, {0, 125},
    {4, 125}, {4, 125}, {3, 250}, {1, 250}, {2, 250}, {1, 500}, {0, 250}
};

Staff_t const tiger [] = {
    {M(1), 500}, {M(2), 500}, {M(3), 500}, {M(1), 500}, {M(0), 500},
    {M(1), 500}, {M(2), 500}, {M(3), 500}, {M(1), 500}, {M(0), 500},

    {M(3), 500}, {M(4), 500}, {M(5), 500}, {M(0), 500}, {M(0), 500},
    {M(3), 500}, {M(4), 500}, {M(5), 500}, {M(0), 500}, {M(0), 500},

    {M(5), 250}, {M(6), 250}, {M(5), 250}, {M(4), 250}, {M(3), 500}, {M(1), 500}, {M(0), 500},
    {M(5), 250}, {M(6), 250}, {M(5), 250}, {M(4), 250}, {M(3), 500}, {M(1), 500}, {M(0), 500},

    {M(1), 500}, {L(5), 500}, {M(1), 500}, {M(0), 500},
    {M(1), 500}, {L(5), 500}, {M(1), 500}, {M(0), 500},
};

/*******************************************************************************
** 函数名称: GetNoteCount
** 功能描述: 根据音阶对应的频率
** 参数说明: num: [输入] 音符编码 1-7
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-16
********************************************************************************/
uint16_t GetNote(uint8_t num)
{
    uint16_t note;     //获取相应音阶所对应的频率
    switch(num)
    {
    case 1:
        note = NOTE_1_L;
        break;
    case 2:
        note = NOTE_2_L;
        break;
    case 3:
        note = NOTE_3_L;
        break;
    case 4:
        note = NOTE_4_L;
        break;
    case 5:
        note = NOTE_5_L;
        break;
    case 6:
        note = NOTE_6_L;
        break;
    case 7:
        note = NOTE_7_L;
        break;

    case 8:
        note = NOTE_1_M;
        break;
    case 9:
        note = NOTE_2_M;
        break;
    case 10:
        note = NOTE_3_M;
        break;
    case 11:
        note = NOTE_4_M;
        break;
    case 12:
        note = NOTE_5_M;
        break;
    case 13:
        note = NOTE_6_M;
        break;
    case 14:
        note = NOTE_7_M;
        break;

    case 15:
        note = NOTE_1_H;
        break;
    case 16:
        note = NOTE_2_H;
        break;
    case 17:
        note = NOTE_3_H;
        break;
    case 18:
        note = NOTE_4_H;
        break;
    case 19:
        note = NOTE_5_H;
        break;
    case 20:
        note = NOTE_6_H;
        break;
    case 21:
        note = NOTE_7_H;
        break;

    case 22:
        note = 3600;
        break;
    default :
        note = 0;
        break;
    }
    return note;
}

/*******************************************************************************
** 函数名称: BeepInit
** 功能描述:
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-20
********************************************************************************/
void BeepInit(void) {
    LL_TIM_SetPrescaler(BEEP_TIME, BEEP_Prescaler); //设置4分频

    LL_TIM_EnableIT_UPDATE(BEEP_TIME);    //使能计数器更新中断

    LL_TIM_SetAutoReload(BEEP_TIME, 65535);  //设置定时器的更新值
    BEEP->Mode =BEEP_ONCE;
    // LL_TIM_EnableCounter(BEEP_TIME);         //打开计数器开始计数
}


/*******************************************************************************
** 函数名称: BeepPlay
** 功能描述:
** 参数说明: num: [输入/出]
**			 mode: [输入/出]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-20
********************************************************************************/
void BeepPlay(uint16_t num) {
    switch(num) {

    case BEEP_D1:
        BEEP->Staff = d1;
        BEEP->MaxNum = sizeof(d1) / 4;
        break;

    case BEEP_D2:
        BEEP->Staff = d2;
        BEEP->MaxNum = sizeof(d2) / 4;
        break;
    case BEEP_D3:
        BEEP->Staff = d3;
        BEEP->MaxNum = sizeof(d3) / 4;
        break;
		
    case BEEP_B1:
        BEEP->Staff = b1;
        BEEP->MaxNum = sizeof(b1) / 4;
        break;

    case BEEP_B2:
        BEEP->Staff = b2;
        BEEP->MaxNum = sizeof(b2) / 4;
        break;
		
    case BEEP_B3:
        BEEP->Staff = b3;
        BEEP->MaxNum = sizeof(b3) / 4;
        break;

    case BEEP_BIR:
        BEEP->Staff = birthday;
        BEEP->MaxNum = sizeof(birthday) / 4;
        break;

    case BEEP_TIG:
        BEEP->Staff = tiger;
        BEEP->MaxNum = sizeof(tiger) / 4;
        break;

    default :
        break;
    }
    BeepMode = BEEP_PLAY;    //切换到播放模式
    BEEP->PlayNum = 0xFF;
    BEEP->NextTime = 0;

    BEEP_Printf("播放:%-4d模式:%d\r\n", num);
}

/*******************************************************************************
** 函数名称: BeepClose
** 功能描述: 关闭蜂鸣器
** 参数说明: : [输入/出] 
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-20
********************************************************************************/
void BeepClose(void) {
    BEEP->Mode = BEEP_ClOSE;
}

/*******************************************************************************
** 函数名称: BeepSetMode
** 功能描述: 设置蜂鸣器的播放模式
** 参数说明: mode: [输入/出] 
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-20
********************************************************************************/
void BeepSetMode(uint8_t mode) {
	    BEEP->Mode = mode;
}
/*******************************************************************************
** 函数名称: BeepScan
** 功能描述: 蜂鸣器扫描函数，放入定时器中
** 参数说明: time: [输入/出]
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-16
********************************************************************************/
void BeepScan(uint32_t time) {

    switch (BeepMode)
    {
    case BEEP_ClOSE:  //光闭蜂鸣器
        if(LL_TIM_IsEnabledCounter(BEEP_TIME)) {
            BEEP_Printf("停止播放%d\r\n", BeepMode);
            LL_TIM_DisableCounter(BEEP_TIME);    //关闭定时器
        }
        LL_GPIO_ResetOutputPin(BEEP_GPIO_Port, BEEP_Pin);
        break;

    case BEEP_PLAY:       //播放模式
        if(BEEP->NextTime <= time) {  //判断是否切换到下一个音符
            BEEP->PlayNum++;  //切换到下一个
            BEEP_Printf("当前播放PlayNum:%d\r\n", BEEP->PlayNum);
            if(BEEP->PlayNum < BEEP->MaxNum) { //还没有播放结束
                const	 Staff_t * st =  &BEEP->Staff[BEEP->PlayNum];   //获取当前音符数据的指针
                //		BEEP_Printf("st->note:%d\r\n",st->note);
                //		BEEP_Printf("st->time:%d\r\n",st->time);
                BEEP_Printf("频率:%d\r\n", GetNote(st->note));
                if(st->note != 0) { //表示频率不为零
                    LL_TIM_EnableCounter(BEEP_TIME);	  //打开定时器
									if(st->note<=22){
                    LL_TIM_SetAutoReload(BEEP_TIME, BEEP_GET_FRE_COUNT(GetNote(st->note)));  //设置当前音符的频率
										}else{
                    LL_TIM_SetAutoReload(BEEP_TIME, BEEP_GET_FRE_COUNT((uint16_t)(st->note)*100));  //设置当前音符的频率						
										}
                } else {
                    LL_TIM_DisableCounter(BEEP_TIME);		//暂时关闭定时器停止发生
                    LL_GPIO_ResetOutputPin(BEEP_GPIO_Port, BEEP_Pin);
                }
                BEEP->NextTime = time + st->time;    //设置当前音符的持续时间
            } else if(BEEP->Mode == BEEP_CYCLE) {    //播放结束-循环模式
                BEEP->PlayNum = 0;

            } else {    //播放结束-单次模式
                BEEP_Printf("停止播放:%d\r\n", BEEP->PlayNum);
                BeepMode = BEEP_ClOSE;
            }
        }

        break;
    default:
        BeepMode = BEEP_ClOSE;
        break;
    }
}


/*******************************************************************************
** 函数名称: Beep_IRQHandler
** 功能描述: 蜂鸣器定时器中断处理函数
** 参数说明: None
** 返回说明: None
** 创建人员: YCG
** 创建日期: 2018-12-20
********************************************************************************/
void Beep_IRQHandler(void) {
    LL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin); //翻转引脚
}
/********************************End of File************************************/

